<?php

namespace Plugins\AdminBasic\Http\Admin\Controller;

use App\Middlewares\Admin\AuthenticateMiddleware;
use App\Middlewares\Admin\PermissionsMiddleware;
use App\Models\Attributes\CreateSql;
use App\Models\Model;
use App\Util\Helper;
use App\Util\Response;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Plugins\AdminBasic\Http\Admin\Service\DevAuxService;
use Sc\Util\MysqlStructureSync\MysqlStructureSync;
use Sc\Util\ScTool;
use Sc\Util\Tool\Dir\EachFile;

/**
 * mysql 数据结构同步
 */
#[Controller('admin/plugins/admin-basic/mysql-structure-sync')]
#[Middlewares([AuthenticateMiddleware::class, PermissionsMiddleware::class])]
class MysqlStructureSyncController
{
    #[RequestMapping('')]
    public function index(): string|\Psr\Http\Message\ResponseInterface
    {
        if (!Helper::isDev()) {
            return "非开发环境不允许操作";
        }

        $function = Helper::request()->input('function', 'page');
        $args     = Helper::request()->input('args', []);

        if ($function === 'detect') {
            $dirs = [BASE_PATH . '/app/Models', BASE_PATH . '/plugins'];
            $structures = [];
            foreach ($dirs as $dir) {
                if (!is_dir($dir)){
                    continue;
                }
                ScTool::dir($dir)->each(function (EachFile $file) use (&$structures){
                    if (!str_contains($file->filepath, 'Models')){
                        return;
                    }
                    $currentFileContent = file_get_contents($file->filepath);
                    preg_match('/^namespace ([\w\\\]+);\s*$/m', $currentFileContent, $match);
                    if (!$match) {
                        var_dump($file->filepath);
                        return;
                    }
                    $modelNamespace = $match[1];
                    $classname      = $modelNamespace . '\\' . strtr($file->filename, ['.php' => '']);
                    $reflectionClass = new \ReflectionClass($classname);
                    if (!$reflectionClass->isInstantiable() || !$reflectionClass->isSubclassOf(Model::class)) {
                        var_dump($file->filepath);
                        return;
                    }

                    $class          = new $classname();
                    $tableName      = $class->getTable();

                    $prefix = Helper::getConfig('databases.default.prefix');

                    if ($CreateSqlAttributes = $reflectionClass->getAttributes(CreateSql::class)) {
                        $sql = preg_replace('/CREATE\s+TABLE\s+`(\w+)`/i', sprintf("CREATE TABLE `%s`", $prefix . $tableName), $CreateSqlAttributes[0]->newInstance()->sql);
                        $sql = preg_replace("/COLLATE\s+\w+/i", '', $sql);
                        $structures[$prefix .$tableName]  = $sql;
                    }
                });
            }

            $devAuxService = DevAuxService::aop();
            $args['current_structures'] = array_map(function ($tableInfo) use ($devAuxService){
                return ["table_name" => $tableInfo->TABLE_NAME, 'structure' => $devAuxService->getCreateSql($tableInfo->TABLE_NAME)];
            }, $devAuxService->getAllTableInfo());
            $args['current_structures'] = array_column($args['current_structures'], "structure", 'table_name');
            $args['code_structures'] = $structures;
        }

        $res = MysqlStructureSync::main($function, $args);

        if ($function === 'page') {
            return Response::html($res);
        }

        return Response::json()->success($res);
    }
}